package net.yihang;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class TestConn {

    public static final String SAVE_DIR = "C:\\Users\\lenovo\\Desktop\\images";

    public static void main(String[] args) throws IOException {
        String url = "https://list.jd.com/list.html?cat=1620,1621,1626";
        Document doc = Jsoup.connect(url).get();
        Elements items = doc.select("li.gl-item");
        System.out.println("商品数：" + items.size());
        File saveDir = new File(SAVE_DIR);
        if (!saveDir.exists()) {
            saveDir.mkdirs();
        }
        List<String> skus = new ArrayList<>();
        List<Item> images = new ArrayList<>();
        for (Element e : items) {
            String name = e.select("em").text();
            String sku = e.select(".j-sku-item").attr("data-sku");
            String img = e.select("a img").attr("src");
            // 图片有可能是延迟加载的
            if (img == null || img.equals("")) {
                img = e.select("a img").attr("data-lazy-img");
            }
            System.out.printf("【%s】sku(%s) img(%s)\n", name, sku, img);
            skus.add(sku);
            images.add(new Item(sku, img));
        }
        parseJsonForPrice(skus);
        downloadImages(images);
    }

    private static void downloadImages(List<Item> images) {
        int cores = 6;
        ExecutorService executorService = Executors.newFixedThreadPool(cores);
        int n = images.size() / cores; // 每组几个元素
        for (int i = 0; i < cores; i++) {
            List<Item> list;
            if (i == cores - 1) {
                list = images.subList(i * n, images.size());
            } else {
                list = images.subList(i * n, (i + 1) * n);
            }
            executorService.execute(() -> {
                for (Item item : list) {
                    String imgurl = "http:" + item.img;
                    try {
                        System.out.println(Thread.currentThread().getName() + " write:" + item.sku);
                        URLConnection conn = new URL(imgurl).openConnection();
                        InputStream is = conn.getInputStream();
                        String filename = imgurl.substring(imgurl.lastIndexOf("/") + 1);
                        OutputStream os = new FileOutputStream(SAVE_DIR + "\\" + filename);
                        write(is, os);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            System.out.println(list);
        }
        shutdownAndAwaitTermination(executorService);
    }

    static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            pool.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }

    // 价格是重新发一次请求获取的json格式的数据
    private static void parseJsonForPrice(List<String> skus) throws IOException {
        String str = skus.stream().map(s -> "J+" + s).collect(Collectors.joining("%20"));
        ObjectMapper mapper = new ObjectMapper();
        List<Map> list = mapper.readValue(new URL("https://p.3.cn/prices/mgets?skuIds=" + str),
                new TypeReference<List<Map>>() {
                });
        for (Map map : list) {
            System.out.println(map);
        }
    }

    private static void write(InputStream is, OutputStream os) throws IOException {
        byte[] buf = new byte[1024];
        while (true) {
            int len = is.read(buf);
            if (len == -1) break;
            os.write(buf, 0, len);
        }
        is.close();
        os.close();
    }
}

class Item {
    String sku;
    String img;

    public Item(String sku, String img) {
        this.sku = sku;
        this.img = img;
    }

    @Override
    public String toString() {
        return "Item{" +
                "sku='" + sku + '\'' +
                ", img='" + img + '\'' +
                '}';
    }
}
